package com.sunnada.edu.system.pub.common;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class FileUpload {
	
	private String name;
	private String screenType;			//适用屏幕类型
	private int chunk;					//当前碎片数
	private int chunks;					//全部碎片数
	private static final int BUFFER_SIZE = 2 * 1024;
	
	public void upload(Plupload plupload) {
		chunks = plupload.getChunks();  //获取总的碎片数  
        chunk = plupload.getChunk();    //获取当前碎片(从0开始计数) 
		boolean isMultipart = ServletFileUpload.isMultipartContent(plupload.getRequest());
		String rootPath = AppContext.getInstance().getRootPath(); 
		
		if(isMultipart){
			//ServletFileUpload upload = new ServletFileUpload();
            
            	//DiskFileItemFactory diskFactory = new DiskFileItemFactory();  
                // threshold 极限、临界值，即硬盘缓存 1M  
                //  diskFactory.setSizeThreshold(4 * 1024);  
                // repository 贮藏室，即临时文件目录  
                // diskFactory.setRepository(new File("F:/soft/apache-tomcat-6.0.26/webapps/nmedia"));  
              
                //ServletFileUpload upload = new ServletFileUpload(diskFactory);  
                // 设置允许上传的最大文件大小 4M  
                //  upload.setSizeMax(4 * 1024 * 1024);  
            	
            	MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)plupload.getRequest();
            	MultiValueMap<String, MultipartFile> map = multipartRequest.getMultiFileMap();
            	//List fileItems = upload.parseRequest(multipartRequest);
				//FileItemIterator iter = upload.getItemIterator(request);
				
            	Iterator<String> iter = map.keySet().iterator();
				//Iterator iter = fileItems.iterator();  
	            while(iter.hasNext()) {  
	            	 String str = (String) iter.next();  
	                 List<MultipartFile> fileList =  map.get(str);  
	                 for(MultipartFile multipartFile : fileList) {  
	                     //因为只存在一个值,所以最后返回的既是第一个也是最后一个值  
	                     plupload.setMultipartFile(multipartFile);  
	                     
	                     //第一个碎片已经是素材上传时要进行类型验证,通过后才可上传
	                     if(chunk == 0 && "0".equals(plupload.getIsMaterial())) {
	                    	 CommonsMultipartFile cf= (CommonsMultipartFile)multipartFile; 
	                         DiskFileItem fi = (DiskFileItem)cf.getFileItem(); 
	                         File f = fi.getStoreLocation();
	                         if(f.length() > (1024*1024)) {
	                        	 boolean validation = materialFormatValidate(f, plupload); 
		                         if(!validation) {
		                        	 CommonException.setException("上传文件格式不符合！");
		                         }
	                         }
	                     }
	                     
	                     //创建新目标文件  
	                     File targetFile = new File(AppContext.getInstance().getRootPath() + "/temp/");  
	                     if(!targetFile.exists()) {
	                    	 targetFile.mkdirs();
	                     }
	                     targetFile = new File(targetFile.getAbsolutePath() + "/" + plupload.getName());  
	                     
	                     try {
		                     //当chunks>1则说明当前传的文件为一块碎片，需要合并  
		                     if (chunks >= 1) {  
		                         //如果chunk==0,则代表第一块碎片,不需要合并  
		                        
									saveUploadFile(multipartFile.getInputStream(), targetFile, chunk == 0 ? false : true);
								  
		                           
		                         //上传并合并完成，存入实体类
		                         if (chunks - chunk == 1) {  
		                             plupload.setUploadFile(targetFile);
		                             //plupload.setFileName(multipartFile.getOriginalFilename());
		                         }  
		                           
		                     } else {  
		                         //否则直接将文件内容拷贝至新文件  
		                         multipartFile.transferTo(targetFile);
		                         plupload.setUploadFile(targetFile);
	                             //plupload.setFileName(multipartFile.getOriginalFilename());
		                     } 
	                     } catch (IOException e) {
	                    	 e.printStackTrace();
							 CommonException.setException(e.getMessage());
						}
	                 }
	               /* FileItem item = (FileItem)iter.next();  
	                if(item.isFormField()) {  
	                    String name = item.getFieldName();  
	    		        String value = item.getString();  
	    		        if("name".equals(name)){
                            this.name = value;
                        } else if("chunks".equals(name)){
                            this.chunks = Integer.parseInt(value);
                        } else if("chunk".equals(name)){
                            this.chunk = Integer.parseInt(value);
                        } else if("screenType".equals(name)){
                            this.screenType = value;
                        }
	                } else {  
	                	// System.out.println("处理上传的文件 ...");  
	                    
	                    String fileName = item.getName();
	                    File f = getTempFile(item);
	                    
	                    //第一次上传时验证文件格式是否符合
	                    if(chunk == 0) {
	                    	String suffix = getFileSuffix(fileName).toLowerCase();
	                    	if(Constants.VIDEO_SUFFIX.indexOf(suffix) >= 0 || Constants.AUDIO_SUFFIX.indexOf(suffix) >= 0) {
	                    		String t = MediaInfo.getMediaType(f.getAbsolutePath());
		                    	String result = MediaInfo.verifyAudioVideoFormat(f.getAbsolutePath()).toLowerCase();
		                    	if(!"".equals(result)) {
		                    		CommonException.setException(result);
		                    	}
	                    	} else if(Constants.IMAGE_SUFFIX.indexOf(suffix) >= 0) {
	                    		
	                    	} else {
	                    		CommonException.setException("上传文件格式不符合！");
	                    	}
	                    }
	                    
	                    int index = fileName.lastIndexOf("\\");  
	                    fileName = fileName.substring(index + 1, fileName.length());  
	             
	                    long fileSize = item.getSize();  
	             
	                    if("".equals(fileName) && fileSize == 0) {             
	                    	CommonException.setException("文件名为空！");
	                    }  
	                    
	                    String fileDir = rootPath + "upload/temp";

                        File dstFile = new File(fileDir);

                        if (!dstFile.exists()){
                            dstFile.mkdirs();
                        }

                    	//this.name = StringUtils.gbkToUtf8(this.name);

                        File dst = new File(dstFile.getPath()+ "/" + this.name);
                        
                        //System.out.println("chunk: " +chunk + ",chunks:" +chunks);
                        
                        copy(f, dst);
                        
                		if (chunk == chunks - 1) {
                			String filePath = dst.getAbsolutePath();
                			HashMap<String, String> map = new HashMap<String, String>();
                			
                			String fileType = getFileType(fileName, filePath);			//获取上传文件的类型
     	                    String fileConfigPath = "";
     	                    
     	                    if(Constants.ELEMENT_TYPE1.equals(fileType)) {
     	                    	 fileConfigPath = Common.getConfigValue("video") + df.format(new Date());
     	                    } else if(Constants.ELEMENT_TYPE2.equals(fileType)) {
     	                    	 fileConfigPath = Common.getConfigValue("picture") + df.format(new Date());
     	                    } else if(Constants.ELEMENT_TYPE5.equals(fileType)) {
     	                    	 fileConfigPath = Common.getConfigValue("bgmusic") + df.format(new Date());
     	                    } 
     	                    
     	                    if (!new File(rootPath + fileConfigPath).exists()){
     	                    	new File(rootPath + fileConfigPath).mkdirs();
     	                    }
                			
                			map.put("fileName", fileName);
                			map.put("storeName", this.name);
                			map.put("screenType", this.screenType);
                			map.put("fileSize", Utils.toString(dst.length()));
                			map.put("remarks", "");
	                    	map.put("fileType", fileType);
	                    	
	                    	if(Constants.ELEMENT_TYPE1.equals(fileType)) {
	                    		String info = MediaInfo.getVideoInfo(filePath);
	                    		if(!"".equals(info)) {
	                    			String t[] = info.split(",");
	                    			map.put("playTime", t[0]);
	                    			map.put("videoWidth", t[1]);
	                    			map.put("videoHeight", t[0]);
	                    			
	                    			String videoJpgPath =  Common.getConfigValue("stuffpreviewPicture") + df.format(new Date());
	                    			
	                    			map.put("videoJpgPath", videoJpgPath + "/" + getFileName(this.name) + ".jpg");
	                    			
	                    			videoJpgPath = rootPath + videoJpgPath;
	                    			
	                    			if (!new File(videoJpgPath).exists()){
	                    				new File(videoJpgPath).mkdirs();
	                                }
	                    			
	                    			VideoUtils.catchVideoJPG(filePath, videoJpgPath + "/" + getFileName(this.name) + ".jpg", Constants.VIDEO_JPG_WIDTH, Constants.VIDEO_JPG_HEIGHT);
	                				
	                    			String videoFlvPath = Common.getConfigValue("stuffpreviewVideo") + df.format(new Date());
	                    			
	                    			map.put("videoFlvPath", videoFlvPath + "/" + getFileName(this.name) + ".flv");
	                    			
	                    			videoFlvPath = rootPath + videoFlvPath;
	                    			
	                    			if (!new File(videoFlvPath).exists()){
	                    				new File(videoFlvPath).mkdirs();
	                                }
	                    			
	                    			VideoUtils.convertVideoToFlv(filePath, videoFlvPath + "/" + getFileName(this.name) + ".flv");

	                    			map.put("filePath", fileConfigPath + "/" + this.name);
	                    		} else {
	                    			CommonException.setException("获取文件信息失败！");
	                    		}
	                    	} else if(Constants.ELEMENT_TYPE5.equals(fileType)) {
	                    		String info = MediaInfo.getAudioInfo(filePath);
	                    		if(!"".equals(info)) {
	                    			map.put("playTime", info.split(",")[0]);
	                    		} else {
	                    			CommonException.setException("获取文件信息失败！");
	                    		}
	                    		map.put("filePath", fileConfigPath + "/" + this.name);
	                    	} else if(Constants.ELEMENT_TYPE2.equals(fileType)) {
	                    		String stuffPreviewUrl = "";
	                    		ImageIcon image = new ImageIcon(filePath);
	            				map.put("imgWidth", Utils.toString(image.getIconWidth()));
	            				map.put("imgHeight", Utils.toString(image.getIconHeight()));
	            				
	            				if ("gif".equals(getFileSuffix(this.name))) {				// gif不需要截图
	            					stuffPreviewUrl = fileConfigPath + "/" + this.name;
	        					} else {	
	        						try {
	        							String jpgPath = Common.getConfigValue("stuffpreviewPicture") + df.format(new Date());
		                    			
	        							map.put("stuffPreviewUrl", jpgPath + "/" + getFileName(this.name) + ".jpg");
	        							
	        							jpgPath = rootPath + jpgPath;
	        							
		                    			if (!new File(jpgPath).exists()){
		                    				new File(jpgPath).mkdirs();
		                                }
	        							stuffPreviewUrl = jpgPath + "/" + getFileName(this.name) + ".jpg";
										PictureUtils.resize(new File(filePath),	new File(stuffPreviewUrl), 250, "jpg");
									} catch (IOException e) {
										e.printStackTrace();
										CommonException.setException("图片压缩失败！");
									}
	        					}
	            				
	            				map.put("filePath", fileConfigPath + "/" + this.name);
	                    	}
	                    	
	                    	copy(dst, new File(rootPath + fileConfigPath + "/" + this.name));			//将临时文件复制到对应目录下
	                    	dst.delete();			//最终将上传上来临时存放的文件删除
                			
                			return map;
                		}
	                }  */
	            }
		}
	}
	
	/**explain 获取文件后缀名
	 * @author niujs 2014-12-11
	 * update niujs 2014-12-11
	 * @param fileName 文件全名 aa.jpg
	 * @return String 后缀 jpg
	 */
	private String getFileSuffix(String fileName) {
		String t[] = fileName.split("\\.");
		if(t.length>1) {
			return t[t.length-1].toLowerCase();
		} else {
			return "";
		}
	}
	
	/**explain 获取文件名
	 * @author niujs 2014-12-11
	 * update niujs 2014-12-11
	 * @param fileName 文件全名 aa.jpg
	 * @return String 文件名 aa
	 */
	private String getFileName(String fileName) {
		String t[] = fileName.split("\\.");
		return t[0];
	}
	
	private String getFileType(String fileName, String filePath) {
		String fileType = "";
		String suffix = getFileSuffix(fileName).toLowerCase();
		if(Constants.VIDEO_SUFFIX.indexOf(suffix) >= 0 || Constants.AUDIO_SUFFIX.indexOf(suffix) >= 0) {
        	fileType = MediaInfo.getAudioVideoType(filePath);
        	if(fileType == null || "".equals(fileType)) {
        		CommonException.setException("获取视频或音频类型失败！");
        	}
		} else if(Constants.IMAGE_SUFFIX.indexOf(suffix) >= 0) {
    		fileType = Constants.ELEMENT_TYPE2;
    	} else {
    		CommonException.setException("上传文件格式不符合！");
    	}
		
		return fileType;
	}
	
	/**explain 获取上传时生成的临时tmp文件
	 * @author niujs 2014-12-11
	 * update niujs 2014-12-11
	 * @param item
	 * @return File 临时文件
	 */
	private File getTempFile(FileItem item) {
		String[] items=(item.toString()).split(",");
		HashMap<String, String> map = new HashMap<String, String>();
		for(int i=0;i<items.length;i++) {
			String[] t = items[i].split("=");
			map.put(t[0].trim(), t[1].trim());
		}
		String store = map.get("StoreLocation");
        File f = new File(store);
        return f;
	}
	
	/**explain 文件上传的传输方法
	 * @author niujs 2014-12-11
	 * update niujs 2014-12-11
	 * @param src
	 * @param dst void
	 */
	private void copy(File src, File dst) {
		InputStream in = null;
		OutputStream out = null;
		
		try {
			if (dst.exists()) {
				out = new BufferedOutputStream(new FileOutputStream(dst, true),
						BUFFER_SIZE);
			} else {
				out = new BufferedOutputStream(new FileOutputStream(dst),
						BUFFER_SIZE);
			}
			in = new BufferedInputStream(new FileInputStream(src), BUFFER_SIZE);

			byte[] buffer = new byte[BUFFER_SIZE];
			int len = 0;
			while ((len = in.read(buffer)) > 0) {
				out.write(buffer, 0, len);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (null != out) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
     
	private boolean materialFormatValidate(File file, Plupload plupload) {
		String fileName = plupload.getName();
		String suffix = getFileSuffix(fileName).toLowerCase();
    /*	if(Constants.VIDEO_SUFFIX.indexOf(suffix) >= 0 || Constants.AUDIO_SUFFIX.indexOf(suffix) >= 0) {
        	return true;
    	} else if(Constants.IMAGE_SUFFIX.indexOf(suffix) >= 0) {
    		return true;
    	} else {
    		return false;
    	}*/
    	return true;
	}
	
	 /** 
     * 保存上传文件，兼合并功能 
     */  
    private static void saveUploadFile(InputStream input, File targetFile, boolean append) throws IOException {  
        OutputStream out = null;  
        try {  
            if (targetFile.exists() && append) {  
                out = new BufferedOutputStream(new FileOutputStream(targetFile, true), BUFFER_SIZE);  
            } else {  
                out = new BufferedOutputStream(new FileOutputStream(targetFile), BUFFER_SIZE);  
            }  
              
            byte[] buffer = new byte[BUFFER_SIZE];  
            int len = 0;  
            //写入文件  
            while ((len = input.read(buffer)) > 0) {  
                out.write(buffer, 0, len);  
            }  
        } catch (IOException e) {  
            throw e;  
        } finally {  
            //关闭输入输出流  
            if (null != input) {  
                try {  
                    input.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            if (null != out) {  
                try {  
                    out.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    } 
    
    public static String getUUIDName(String fileName) {
		String[] split = fileName.split("\\.");
		String extendFile = "." + split[split.length - 1].toLowerCase();
		MyDateBean my = new MyDateBean();
		//return java.util.UUID.randomUUID().toString() + extendFile;
		return "res-"+my.Format("yyyyMMddHHmmssSSS")+extendFile;
	}
    
}